package com.polaris.live.common.util

import java.util.Collections
import java.util.concurrent.ConcurrentHashMap

/**
 * StructUtils
 *
 * @author Created by lucas on 2023/10/19 11:05
 */
object StructUtils {

    /**
     * 创建一个安全的set
     */
    fun <T> newSaleSet(): MutableSet<T> {
        return if (SystemUtils.isSdkInt24()) {
            ConcurrentHashMap.newKeySet()
        } else {
            return Collections.newSetFromMap(ConcurrentHashMap())
        }
    }
}

/**
 * 过滤key或者value为空的entry
 */
@Suppress("UNCHECKED_CAST")
fun <K, V> Map<K?, V?>.filterNotNull(): Map<K, V> {
    return filter { it.key != null && it.value != null } as Map<K, V>
}

/**
 * 过滤key为空的entry
 */
@Suppress("UNCHECKED_CAST")
fun <K, V> Map<K?, V>.filterNotNullKeys(): Map<K, V> {
    return filter { it.key != null } as Map<K, V>
}

/**
 * 过滤value为空的entry
 */
@Suppress("UNCHECKED_CAST")
fun <K, V> Map<K, V?>.filterNotNullValues(): Map<K, V> {
    return filter { it.value != null } as Map<K, V>
}

/**
 * 转换为不为空的map
 */
inline fun <T, K, V> Iterable<T>.associateNotNull(transform: (T) -> Pair<K, V>?): Map<K, V> {
    val destination = LinkedHashMap<K, V>()
    for (item in this) {
        val pair = transform(item)
        if (pair != null) {
            destination.put(pair.first, pair.second)
        }
    }
    return destination
}

/**
 * 转换为不为空的map，严格的，只有2个都不为空才会添加
 */
inline fun <T, K, V> Iterable<T>.associateNotNullStrict(transform: (T) -> Pair<K?, V?>): Map<K, V> {
    val destination = LinkedHashMap<K, V>()
    for (item in this) {
        val (k, v) = transform(item)
        if (k != null && v != null) {
            destination.put(k, v)
        }
    }
    return destination
}

/**
 * 如果是true则执行，否则返回空
 */
inline fun <T> Boolean.ifThen(block: () -> T): T? = if (this) block() else null

/**
 * 如果是false则执行，否则返回空
 */
inline fun <T> Boolean.ifNotThen(block: () -> T): T? = if (!this) block() else null

/**
 * 如果是true则执行，否则返回自己
 */
inline fun <T> T.ifThen(test: Boolean, block: T.() -> T) = if (test) block() else this

/**
 * 线程安全的获取数据
 */
fun <K : Any, V> MutableMap<K, V>.computeIfAbsentBy21(key: K, block: (K) -> V): V {
    return if (SystemUtils.isSdkInt24()) {
        computeIfAbsent(key, block)
    } else {
        get(key) ?: synchronized(key) {
            //双重检查
            val r2 = get(key)
            if (r2 != null) {
                return r2
            } else {
                block(key).apply {
                    put(key, this)
                }
            }
        }
    }
}

/**
 * 删除集合中符合条件的元素
 */
fun <E> MutableCollection<E>.removeIfBy24(filter: (E) -> Boolean): Boolean {
    return if (SystemUtils.isSdkInt24()) {
        removeIf(filter)
    } else {
        var removed = false
        val each = iterator()
        while (each.hasNext()) {
            if (filter.invoke(each.next())) {
                each.remove()
                removed = true
            }
        }
        removed
    }
}

/**
 * 转换为int
 */
fun Boolean.toInt(): Int {
    return if (this) {
        1
    } else {
        0
    }
}

/**
 * 加载数据，如果有则加载，没有则生成
 */
fun <T> loadIfPresent(get: () -> T?, gen: LoadBuilder<T>.() -> Unit, set: (T) -> Unit) {
    val sourceValue = get()
    if (sourceValue != null) {
        set(sourceValue)
    } else {
        gen(LoadBuilder(set))
    }
}

class LoadBuilder<T>(
    private val set: (T) -> Unit
) {

    fun emit(t: T) {
        set(t)
    }
}